package iaccounts

import (
	"context"

	"gitee.com/djaf/my-certs/app/classes/accounts"
	"gitee.com/djaf/my-certs/app/classes/keypairs"
	"gitee.com/djaf/my-certs/app/data/dxo"
	"gitee.com/djaf/my-certs/app/data/entity"
	"gitee.com/djaf/my-certs/app/web/dto"
)

// ServiceImpl ...
type ServiceImpl struct {

	//starter:component

	_as func(accounts.Service) //starter:as("#")

	Dao            accounts.DAO     //starter:inject("#")
	KeyPairService keypairs.Service //starter:inject("#")

}

func (inst *ServiceImpl) _impl() accounts.Service {
	return inst
}

// Find ...
func (inst *ServiceImpl) Find(ctx context.Context, id dxo.AccountID) (*dto.Account, error) {
	item1, err := inst.Dao.Find(nil, id)
	if err != nil {
		return nil, err
	}
	return accounts.ConvertE2D(item1)
}

// List ...
func (inst *ServiceImpl) List(ctx context.Context, q *accounts.Query) ([]*dto.Account, error) {
	list, err := inst.Dao.List(nil, q)
	if err != nil {
		return nil, err
	}
	return accounts.ConvertListE2D(list)
}

// Insert ...
func (inst *ServiceImpl) Insert(ctx context.Context, item1 *dto.Account) (*dto.Account, error) {

	kp1 := new(dto.KeyPair)
	kp1.Algorithm = "RSA"
	kp2, err := inst.KeyPairService.CreateNew(ctx, kp1)
	if err != nil {
		return nil, err
	}

	item2, err := accounts.ConvertD2E(item1)
	if err != nil {
		return nil, err
	}

	item2.KeyPair = kp2.ID

	item3, err := inst.Dao.Insert(nil, item2)
	if err != nil {
		return nil, err
	}

	return accounts.ConvertE2D(item3)
}

// Update ...
func (inst *ServiceImpl) Update(ctx context.Context, id dxo.AccountID, item1 *dto.Account) (*dto.Account, error) {

	item2, err := inst.Dao.Update(nil, id, func(ent *entity.Account) {
		ent.Owner = item1.Owner
		ent.Group = item1.Group
		ent.Updater = 0 // todo: = current.user
	})

	if err != nil {
		return nil, err
	}

	return accounts.ConvertE2D(item2)
}

// Remove ...
func (inst *ServiceImpl) Remove(ctx context.Context, id dxo.AccountID) error {
	return inst.Dao.Remove(nil, id)
}

// GetCurrent ...
func (inst *ServiceImpl) GetCurrent(ctx context.Context) (*dto.Account, error) {
	const sel = 1
	item1, err := inst.Dao.FindBySelector(nil, sel)
	if err != nil {
		return nil, err
	}
	return accounts.ConvertE2D(item1)
}

// SignUp ...
func (inst *ServiceImpl) SignUp(ctx context.Context, id dxo.AccountID, item *dto.Account) (*dto.Account, error) {
	task := new(accountSignUpTask)
	task.service = inst
	task.serviceAPI = inst
	task.accountDTO = item
	task.accountID = id
	task.context = ctx
	err := task.run()
	if err != nil {
		return nil, err
	}
	return item, nil
}
